#Binary parser template

import os, sys
from Sanae3D.lib.ModelObject import Model3D
from Sanae3D.lib.StructReader import StructReader

class BattleOfTheImmortals_M4F(Model3D):
        
    def __init__(self, obj3D=None, outFile=None, inFile=None):
        
        super(BattleOfTheImmortals_M4F,self).__init__("XAC")
        self.obj3D = obj3D
        self.inFile = inFile
        self.outFile = outFile
        
    def parse_textures(self, numTex, texOffset):
        
        self.inFile.seek(texOffset)
        
        print "%d textures" %numTex
        for i in xrange(numTex):
            texName = os.path.basename(self.inFile.read_string(292, '\x00'))
            print texName
            self.create_material(i)
            self.add_material_name(i, "material[%d]" %i)
            self.add_texture_name(i, texName)
            
    def parse_bones(self, numBones, offset):
        
        self.inFile.seek(offset)
        for i in xrange(numBones):
            boneName = self.inFile.read_string(80, "\x00")
            self.inFile.seek(252, 1)
            
    def parse_vertices(self, meshName, numVerts, offset):
        
        self.inFile.seek(offset)
        for i in xrange(numVerts):
            vx, vz, vy = self.inFile.read_float(3)
            
            self.create_vertex(meshName, i)
            self.add_coords(meshName, i, [vx, vy, -vz])
            
    def parse_faces(self, meshName, numFaces, matNum, offset):
        
        self.inFile.seek(offset)
        for i in xrange(numFaces):
            v1, v2, v3 = self.inFile.read_short(3)
            self.create_face(meshName, i)
            self.add_face_verts(meshName, i, [v1, v2, v3])
            self.add_face_material(meshName, i, matNum)
            
    def parse_normals(self, meshName, numNorm, offset):
        
        self.inFile.seek(offset)
        for i in xrange(numNorm):
            nx, nz, ny = self.inFile.read_float(3)
            self.add_vert_normals(meshName, i, [nx, ny, -nz])
            
    def parse_uv(self, meshName, numUV, offset):
        
        self.inFile.seek(offset)
        for i in xrange(numUV):
            tu, tv = self.inFile.read_float(2)
            self.add_vert_uv(meshName, i, [tu, tv])
            
    def parse_meshes(self, numMesh, meshOffset):
        
        self.inFile.seek(meshOffset)
        print "%d meshes" %numMesh
        
        for i in xrange(numMesh):
            meshName = self.inFile.read_string(80, '\x00')
            meshName = "%s[%d]" %(meshName, self.mesh_count())
            unk1, matNum, unk2, unk3, unk4, unk5 = self.inFile.read_long(6)
            
            numVerts, vertOffset = self.inFile.read_long(2)
            numFaces, faceOffset = self.inFile.read_long(2)
            numNorm, normOffset = self.inFile.read_long(2)
            unk = self.inFile.read_long(2)
            numUV, uvOffset = self.inFile.read_long(2)
            numBones, boneOffset = self.inFile.read_long(2)
            self.inFile.seek(72, 1)
            print meshName
            
            curPos = self.inFile.tell()
            self.create_object(meshName)
            self.parse_vertices(meshName, numVerts, vertOffset)
            self.parse_faces(meshName, numFaces, matNum, faceOffset)
            self.parse_normals(meshName, numNorm, normOffset)
            self.parse_uv(meshName, numUV, uvOffset)
            
            #next mesh
            self.inFile.seek(curPos)
            
    def parse_unk_section(self, unkCount, offset):
        '''First unknown section, after textures'''
        
        self.inFile.seek(offset)
        
        for i in xrange(unkCount):
            self.inFile.read_long(8)
            count, unkOffset = self.inFile.read_long(2)
            self.inFile.seek(32, 1)
            
            curPos = self.inFile.tell()
            self.inFile.seek(unkOffset)
            for j in xrange(count):
                self.inFile.read_float(16)
            self.inFile.seek(curPos)
        
    def parse_file(self):
        '''Main parser method. Can be replaced'''
        
        idstring = self.inFile.read_long()
        numTex, texOffset, num2, offset2, numMesh, meshOffset, numBones, \
              boneOffset, num5, offset5, num6, offset6, num7, \
              offset7 = self.inFile.read_long(14)
        
        self.parse_unk_section(num2, offset2)
        self.parse_textures(numTex, texOffset)
        self.parse_meshes(numMesh, meshOffset)
        

def read_file(path):
    '''Read the file'''
    
    openFile = StructReader(open(path, 'rb'))
    obj = BattleOfTheImmortals_M4F(inFile=openFile)
    obj.parse_file()
    openFile.close()
    return obj

def write_file(path):
    
    pass

def definitions():
    '''Return the header, extension, and a description of the format'''
    
    return "\xC9\x8D\x32\x01", "M4F", "Battle of the Immortals m4f"

if __name__ == '__main__':
    
    file1 = "Treasure_AiJi_05.m4f"
    file2 = "bbrd_tx_damaoxianjia_01.m4f"
    file3 = "undead_bingmayong_1.m4f"
    obj = read_file(file1)